package com.zzc.handler;

import com.zzc.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Map;

/**
 * 接口拦截
 *
 * @author zzc
 */
@Component
public class AccessHandlerInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //判断是否是映射到方法上的注解
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            //获取AccessLimit注解
            AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
            //没有AccessLimit注解，直接通过
            if (accessLimit == null) {
                return true;
            }
            //获得AccessLimit注解的参数
            int seconds = accessLimit.seconds();
            int maxCount = accessLimit.maxCount();
            //获取RESTful风格请求链接中的参数，用户数据
            Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            //System.out.println(pathVariables.toString());
            String userId = (String) pathVariables.get("userId");
            String productId = (String) pathVariables.get("productId");
            //从redis缓存中获得该用户的id以及商品的id
            Integer count = (Integer) redisUtil.get("Limit_" + userId + "_" + productId);
            //如果缓存中不存在，就创建对应的键值对
            if (count == null) {
                redisUtil.set("Limit_" + userId + "_" + productId, 1, seconds);
                return true;
            } else if (count > maxCount) {
                //访问次数大于最大次数，拒绝访问
                response.setContentType("application/json;charset=UTF-8");
                OutputStream out = response.getOutputStream();
                String str = JSON.toJSONString("请求过于频繁");
                out.write(str.getBytes("UTF-8"));
                out.flush();
                out.close();
                return false;
            } else {
                //访问次数+1
                redisUtil.incr("Limit_" + userId + "_" + productId, 1L);
                return true;
            }

        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
